package net.wanho.commons.servlet;

import com.alibaba.fastjson.JSON;
import net.wanho.commons.factory.BeanFactory;
import net.wanho.commons.service.BaseService;
import net.wanho.commons.vo.AjaxResult;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public abstract class BaseServlet<S extends BaseService> extends HttpServlet {
    protected S baseService ;
    public BaseServlet() {
        //动态获得 泛型 参数类型
        Type genType = this.getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        Class serviceCls =  (Class)params[0];
        this.baseService = BeanFactory.getBean(serviceCls) ;
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            //设置post请求 中文乱码
            req.setCharacterEncoding("UTF-8");
            resp.setContentType("text/html;charset=UTF-8");
            String method = req.getParameter("method");
            Method m = this.getClass().getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);
            m.setAccessible(true);
            //通过反射调用 子类的方法  获得返回值 returnVal
            Object returnVal = m.invoke(this,req,resp) ;
            // 兼容 适配 该子类的方法返回值
            // 【同步：跳转页面 String /验证码 字节字符流 void 】  【异步：AjaxResult】
            //获得被执行的子类的返回类型
            Class<?> returnType = m.getReturnType();
            // 验证码 字节字符流 void
            if (returnType==void.class){
                return;
            }
            // 返回 string 同步：跳转页面
            if (returnType==String.class){
                String url = (String) returnVal;
                // 客户端跳转  redirect   "redirect:/admin/list.jsp"
                if (url.startsWith("redirect:")){
                    resp.sendRedirect(req.getContextPath()+url.substring("redirect:".length()));
                    return;
                }
                //服务器内部跳转 [默认服务器内部跳转]  forward  "/admin/list.jsp"
                req.getRequestDispatcher(url).forward(req,resp);
                return;
            }
            // 返回 AjaxResult 【异步：AjaxResult】
            if (returnType == AjaxResult.class){
                AjaxResult ajaxResult = (AjaxResult) returnVal;
                String strJSON = JSON.toJSONString(ajaxResult);
                resp.getWriter().print(strJSON);
                return;
            }
            resp.sendError(503,"兼容 适配 该子类的方法返回值 只支持 void String AjaxResult...");
        }catch (Exception  e) {
            e.printStackTrace();
            resp.sendError(500,"服务器升级中...");
        }
    }

    protected  <T> T parseRequest(HttpServletRequest request,Class<T> pojoCls){
        try {
            T instance = pojoCls.newInstance();
            return getT(request, instance);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage()) ;
        }
    }

    //自动获取request的页面上的内容，创建对象并且封装起来
    private <T> T getT(HttpServletRequest request, Object instance) {
        try {
            ConvertUtils.register(new Converter() {
                public Object convert(Class type, Object value) {
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                    try {
                        return simpleDateFormat.parse(value.toString());
                    } catch (ParseException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    return null;
                }
            }, Date.class);
            BeanUtils.populate(instance,request.getParameterMap());
            return (T) instance;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("解析请求参数到pojo异常....") ;
        }
    }

    protected void parseRequest(HttpServletRequest request,Object pojoInstance){
        try {
            BeanUtils.populate(pojoInstance,request.getParameterMap());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("解析请求参数到pojo异常....") ;
        }
    }
}
